Imports System.Windows.Forms
Namespace UI.Windows
  ''' <summary>
  ''' Control helper class.
  ''' </summary>
  Public NotInheritable Class ControlsHelper

    ''' <summary>
    ''' Clears the controls.
    ''' </summary>
    ''' <param name="parent">The parent Control.</param>
    Shared Sub ClearControls(ByVal parent As Control)

      ClearControls(parent, String.Empty, False)

    End Sub

    ''' <summary>
    ''' Clears the controls.
    ''' </summary>
    ''' <param name="parent">The parent Control.</param>
    ''' <param name="tag">The tag name to use when searching for controls to clear.</param>
    Shared Sub ClearControls(ByVal parent As Control, ByVal tag As String)

      ClearControls(parent, tag, False)

    End Sub

    ''' <summary>
    ''' Clears controls.
    ''' </summary>
    ''' <param name="parent">The parent Control.</param>
    ''' <param name="clearChildren">if set to <c>true</c> [clear children].</param>
    Shared Sub ClearControls(ByVal parent As Control, ByVal clearChildren As Boolean)

      ClearControls(parent, String.Empty, clearChildren)

    End Sub

    ''' <summary>
    ''' Clears the controls.
    ''' </summary>
    ''' <param name="parent">The parent Control.</param>
    ''' <param name="tag">The tag name to use when searching for controls to clear.</param>
    ''' <param name="clearChildren">if set to <c>true</c> [clear children].</param>
    Shared Sub ClearControls(ByVal parent As Control, ByVal tag As String, ByVal clearChildren As Boolean)

      If parent Is Nothing Then
        Throw New ArgumentNullException("parent")
      End If

      parent.SuspendLayout()

      Try
        ClearKnownControls(parent, tag, clearChildren)
      Finally
        parent.ResumeLayout()
      End Try

    End Sub

    ''' <summary>
    ''' Selects the first empty control.
    ''' </summary>
    ''' <param name="parent">The parent Control.</param>
    ''' <param name="tag">The tag name to use when searching for controls.</param>
    ''' <param name="includeChildren">if set to <c>true</c> [include children].</param>
    ''' <remarks>Searches by tab order.</remarks>
    Shared Sub SelectFirstEmptyControl(ByVal parent As Control, ByVal tag As String, ByVal includeChildren As Boolean)

      parent.SuspendLayout()

      Dim controls As System.Collections.Generic.SortedDictionary(Of String, Control) = FindControls(parent, tag, includeChildren)

      For Each key As String In FindControls(parent, tag, includeChildren).Keys
        Dim tempControl As Control = controls.Item(key)

        If tempControl.Text.Length = 0 Then
          tempControl.Select()
          Exit For
        End If

      Next

      parent.ResumeLayout()

    End Sub

    ''' <summary>
    ''' Finds all the controls within a partent control.
    ''' </summary>
    ''' <param name="parent">Parent <see cref="Control">Control</see>.</param>
    ''' <param name="tag">Narrow search by tag <see cref="String">name</see>.</param>
    ''' <param name="includeChildren">Include child <see cref="Control">Controls</see>.</param>
    ''' <returns><see cref="System.Collections.Generic.SortedDictionary(Of String, Control)">List</see> of controls.</returns>
    ''' <remarks></remarks>
    Public Shared Function FindControls(ByVal parent As Control, ByVal tag As String, ByVal includeChildren As Boolean) As System.Collections.Generic.SortedDictionary(Of String, Control)

      Dim controls As New System.Collections.Generic.SortedDictionary(Of String, Control)

      For Each childControl As Control In parent.Controls

        If Not String.IsNullOrEmpty(tag) AndAlso Not childControl.Tag.Equals(tag) Then
          Continue For
        End If

        SearchForControls(childControl, tag, includeChildren, controls)

      Next

      Return controls

    End Function

    Private Shared Sub SearchForControls(ByVal childControl As Control, ByVal tag As String, ByVal includeChildren As Boolean, ByRef controls As System.Collections.Generic.SortedDictionary(Of String, Control))
      'Determine TabIndex
      If childControl.TabStop Then
        controls.Add(GetTabIndex(childControl), childControl)
      End If

      If includeChildren AndAlso childControl.HasChildren Then
        For Each child As Control In childControl.Controls
          SearchForControls(child, tag, True, controls)
        Next
      End If

    End Sub

    Private Shared Sub ClearKnownControls(ByVal parent As Control, ByVal tag As String, ByVal clearChildren As Boolean)
      For Each childControl As Control In parent.Controls

        If Not String.IsNullOrEmpty(tag) And (IsNothing(childControl.Tag) Or (Not IsNothing(childControl.Tag) AndAlso Not childControl.Tag.Equals(tag))) Then
          Continue For
        End If

        ClearControl(childControl)

        If clearChildren AndAlso childControl.HasChildren Then
          ClearKnownControls(childControl, tag, True)
        End If

      Next

    End Sub

    Private Shared Sub ClearControl(ByVal childControl As Control)

      Select Case TypeName(childControl)

        Case Is = "TextBox", "MaskedTextBox"
          Dim tempTextBox As TextBoxBase = DirectCast(childControl, TextBoxBase)
          If Not tempTextBox.ReadOnly Then
            tempTextBox.Text = String.Empty
          End If

        Case Is = "CheckedListBox"
          Dim tempCheckedListBox As CheckedListBox = DirectCast(childControl, CheckedListBox)
          tempCheckedListBox.ClearSelected()

          For Each checkedItem As Object In tempCheckedListBox.CheckedIndices
            tempCheckedListBox.SetItemCheckState(CInt(checkedItem), CheckState.Unchecked)
          Next

        Case Is = "ComboBox"
          DirectCast(childControl, System.Windows.Forms.ComboBox).SelectedIndex = -1

        Case Is = "DateTimePicker"
          Dim picker As DateTimePicker = DirectCast(childControl, System.Windows.Forms.DateTimePicker)
          picker.Value = Now
          If picker.ShowCheckBox Then
            picker.Checked = False
          End If

        Case Is = "CheckBox"
          DirectCast(childControl, System.Windows.Forms.CheckBox).Checked = False

        Case Is = "RadioButton"
          DirectCast(childControl, System.Windows.Forms.RadioButton).Checked = False

        Case Is = "ListBox"
          DirectCast(childControl, System.Windows.Forms.ListBox).SelectedIndex = -1

        Case Is = "ListView"
          Dim tempListView As ListView = DirectCast(childControl, ListView)

          For Each checkedItem As ListViewItem In tempListView.CheckedItems
            checkedItem.Checked = False
          Next

          For Each selectedItem As ListViewItem In tempListView.SelectedItems
            selectedItem.Selected = False
          Next

        Case Is = "MonthCalendar"
          DirectCast(childControl, MonthCalendar).SetDate(Now)

        Case Is = "NumericUpDown"
          Dim tempNumbericUpDown As NumericUpDown = DirectCast(childControl, NumericUpDown)
          tempNumbericUpDown.Value = tempNumbericUpDown.Minimum

        Case Is = "ProgressBar"
          Dim tempProgress As ProgressBar = DirectCast(childControl, ProgressBar)
          tempProgress.Value = tempProgress.Minimum

        Case Is = "RichTextBox"
          DirectCast(childControl, System.Windows.Forms.RichTextBox).Text = String.Empty
      End Select

    End Sub

    Private Shared Function GetTabIndex(ByVal inputControl As Control) As String
      Dim tabIndex As String = String.Empty

      tabIndex = inputControl.TabIndex.ToString("00", CultureInfo.InvariantCulture)

      If Not IsNothing(inputControl.Parent) Then
        tabIndex = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", GetTabIndex(inputControl.Parent), tabIndex)
      End If

      Return tabIndex

    End Function

    Private Sub New()
    End Sub

  End Class
End Namespace